<template>
  <div v-loading="loading" class="preview">
    <div v-if="instanceData.instanceId">
      <div class="title-div">
        <div class="title">
          <div v-if="instanceData.staterUser">
            <w-avatar showY :name="instanceData.staterUser.name" :src="instanceData.staterUser.avatar" />
          </div>
          <div class="title-info">
            <div class="name">
              <span style="margin-right: 15px; color:#000;">{{ instanceData.processDefName }}</span>
              <el-tag :type="status.type || 'primary'">{{ status.text }}</el-tag>
            </div>
            <div class="code">
              <span style="color:#6c6c6c;">{{ $t('webAuto.RequestNo') }}：</span>
              <span class="id">{{ instanceData.businessKey }}</span>
            </div>
            <img v-if="status.img" :src="status.img" :style="isMobile ? 'right: -20px' : ''">
            <!--          <div style="font-size: 13px; color: rgb(142 141 141)" v-if="instanceData.staterUser">
                        由 {{instanceData.staterUser.name}} 在{{instanceData.startTime}}发起
                      </div>-->
          </div>
          <div class="extend-options" v-if="!isMobile && instanceData.result === 'PASS'">
            <el-tooltip class="item" effect="dark" :content="$t('webAuto.Print')" placement="top-start">
              <el-icon @click="print" class="icon">
                <Printer />
              </el-icon>
            </el-tooltip>
          </div>
        </div>
      </div>
      <div :class="instanceData.result === 'RUNNING' ? 'container-box' : 'container-box2'">
        <el-row :gutter="20">
          <el-col :span="20" style="border-right: 1px solid #e8e8e8">
            <form-render class="process-form" :config="instanceData.formConfig" :mode="isMobile ? 'MOBILE' : 'PC'"
              ref="form" :instance-id="instanceData.instanceId" :forms="instanceData.formItems"
              v-model="instanceData.formData" />
          </el-col>
          <el-col :span="4">
            <process-progress :result="instanceData.result" :status="instanceData.status"
              :progress="instanceData.progress" />
          </el-col>
        </el-row>
      </div>
      <!-- 表单 -->
      <!-- <div class="form">
        <form-render class="process-form" :config="instanceData.formConfig" :mode="isMobile ? 'MOBILE' : 'PC'"
          ref="form" :instance-id="instanceData.instanceId" :forms="instanceData.formItems"
          v-model="instanceData.formData" />
      </div> -->
      <!-- 审批流程进度 -->
      <!-- <div class="process">
        <process-progress :result="instanceData.result" :status="instanceData.status"
          :progress="instanceData.progress" />
      </div> -->
    </div>
    <div class="actions" v-if="instanceData.result != 'RUNNING'">
      <div class="ok-refuse">
        <el-button type="primary" round @click="copyClick(instanceData)">{{ $t('title.copy') }}</el-button>
      </div>
    </div>
    <div class="actions" v-if="instanceData.result === 'RUNNING' || nodeId == 'root'">
      <div style="position: relative; width: 100%">
        <div class="comment" @click="comment">
          <el-icon class="icon">
            <ChatLineRound />
          </el-icon>
          <div>{{ $t('webAuto.comment') }}</div>
        </div>
        <div style="position: absolute; left: 95px; top: 0;">
          <el-button type="primary" round @click="copyClick(instanceData)">{{ $t('title.copy') }}</el-button>
        </div>
        <template v-if="instanceData.operationPerm">
          <div v-if="activeTasks.length > 0 && showMore" class="action-more">
            <el-dropdown>
              <el-button type="primary" link>
                {{ $t('webAuto.more') }}<el-icon>
                  <ArrowDown />
                </el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item v-if="opPerms?.transfer?.show" @click="handler('transfer')">
                    <iconify icon="fluent:people-swap-20-filled" style="font-size: 18px; margin-right: 5px" />
                    {{ opPerms?.transfer?.alisa }}
                  </el-dropdown-item>
                  <el-dropdown-item v-if="opPerms?.execute?.show" @click="handler('execute')">
                    <iconify icon="fluent:copy-arrow-right-16-filled" style="font-size: 18px; margin-right: 5px" />
                    {{ opPerms?.execute?.alisa }}
                  </el-dropdown-item>
                  <el-dropdown-item v-if="opPerms?.refuse?.show" @click="handler('refuse')">
                    <iconify icon="material-symbols:assignment-return" style="font-size: 18px; margin-right: 5px" />
                    {{ opPerms?.refuse?.alisa }}
                  </el-dropdown-item>
                  <el-dropdown-item v-if="opPerms?.afterAdd?.show" @click="handler('afterAdd')">
                    <iconify icon="material-symbols:person-add" style="font-size: 18px; margin-right: 5px" />
                    {{ opPerms?.afterAdd?.alisa }}
                  </el-dropdown-item>
                  <el-dropdown-item v-if="enableCancel" @click.native="handler('cancel')">
                    <iconify icon="eva:undo-fill" style="font-size: 18px; margin-right: 5px" />
                    {{ $t('webAuto.revoke') }}
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
          <div v-if="activeTasks.length > 0" class="ok-refuse">
            <!-- <el-button type="danger" v-if="opPerms?.refuse?.show" round plain @click="handler('refuse')">{{opPerms?.refuse?.alisa}}</el-button> -->
            <el-button type="danger" v-if="opPerms?.recall?.show" round plain @click="handler('recall')">{{
              opPerms?.recall?.alisa
            }}</el-button>
            <el-button type="primary" v-if="opPerms?.agree?.show" round @click="handler('agree')">{{
              opPerms?.agree?.alisa
            }}</el-button>
            <el-button type="primary" v-else-if="opPerms?.complete?.show" round @click="handler('complete')">{{
              opPerms?.complete?.alisa }}</el-button>
          </div>
        </template>
        <div class="cancel" v-else-if="enableCancel">
          <el-button type="primary" link @click="handler('cancel')">
            <el-icon>
              <RefreshLeft />
            </el-icon>
            {{ $t('webAuto.revoke') }}
          </el-button>
        </div>
        <div></div>
        <div class="cancel2" v-if="nodeId == 'root' && instanceData.status === '审批再修改'">
          <el-button type="danger" round plain @click="updeatePage">{{ $t('webAuto.ModifyForm') }}</el-button>
        </div>
      </div>
    </div>
    <w-dialog v-model="printVisible" width="700px" :title="$t('webAuto.printPreview')" :okText="$t('webAuto.Print')"
      @ok="doPrint">
      <template #title>
        <div>
          <span>{{ $t('webAuto.printPreview') }}</span>
          <el-radio-group style="margin: 0 30px" v-model="printCheck" @change="renderPrint"
            v-if="printTemplateConfig.customPrint">
            <el-radio :label="false">{{ $t('webAuto.DefaultTemplate') }}</el-radio>
            <el-radio :label="true">{{ $t('webAuto.CustomTemplate') }}</el-radio>
          </el-radio-group>
        </div>
      </template>
      <div v-if="printCheck" id="printDom" ref="print" v-html="printTemplateConfig.printTemplate"></div>
      <default-printer v-else ref="print" :status="status" :instance="instanceData" />
    </w-dialog>
    <w-dialog v-model="actionVisible" :width="isMobile ? '100%' : '500px'" :title="actionDesc.title" okText="提 交"
      @ok="doAction">
      <process-action ref="action" @success="handlerOk" @fail="actionLoading = false" :form-data="formData"
        v-if="actionVisible" :active-tasks="activeTasks" :instance="instanceData" :action="actionType"
        :action-desc="actionDesc" show-sign :graphics="graphics" />
    </w-dialog>
    <!-- 抄送弹框 -->
    <el-dialog v-if="openItemCopy" :title="$t('webAuto.CCProcess')" closeFree width="40%" v-model="openItemCopy">
      <div style="margin-bottom: 10px">
        <span style="margin:20xp 0">{{ $t('webAuto.shouldCopy') }}：</span>
        <el-button style="margin-right: 20px" size="small" icon="user" @click="selectUser">{{ $t('module.selectPeoples')
        }}</el-button>
        <el-tag size="small" v-for="(item, index) in orgPicker.value" :key="index" style="margin-right: 10px">{{
          item.name
        }}</el-tag>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="openItemCopy = false">{{ $t('webAuto.cancel') }}</el-button>
          <el-button type="primary" @click="openItemCopyClick">
            {{ $t('webAuto.sure') }}
          </el-button>
        </div>
      </template>
    </el-dialog>
    <org-picker :pc-mode="!isMobile" :title="orgPicker.title" type="user" ref="orgPicker" :multiple="orgPicker.multiple"
      :selected="orgPicker.selected" @ok="selected" />
  </div>
</template>

<script>
import FormRender from '@/views/common/form/FormRender.vue'
import ProcessProgress from './ProcessProgress.vue'
import ProcessAction from './ProcessAction.vue'
import { getFormAndProcessProgress, updateInstanceFormData } from '@/api/processTask'
import { getCustomPrintConfig } from '@/api/process'
import moment from 'moment'
import { showFailToast } from 'vant'
import Print, { bindVar, getVal } from '@/utils/print'
import DefaultPrinter from './DefaultPrinter.vue'
import OrgPicker from '@/components/common/OrgPicker.vue'
import taskApi from '@/api/processTask'

export default {
  name: 'ProcessInstancePreview',
  components: { DefaultPrinter, FormRender, ProcessProgress, ProcessAction, OrgPicker },
  props: {
    instanceId: {
      type: String,
      required: true,
    },
    nodeId: {
      type: String,
      required: false,
    },
    graphics: {
      type: String,
      default: '',
    },
  },
  computed: {
    loginUser() {
      return this.$store.state.loginUser
    },
    isRootUser() {
      return this.instanceData?.staterUser?.id === this.loginUser?.id
    },
    enableCancel() {
      try {
        return this.instanceData.externSetting.enableCancel
      } catch (e) {
        return false
      }
    },
    isMobile() {
      return window.screen.width < 450
    },
    opPerms() {
      const opPerms = this.instanceData.operationPerm || {}
      for (let key in opPerms) {
        if (!opPerms[key]) {
          opPerms[key] = { alisa: '', show: false }
        }
      }
      return opPerms
    },
    showMore() {
      return this.opPerms?.transfer?.show || this.opPerms?.execute?.show || this.opPerms?.recall?.show
        || this.opPerms?.afterAdd?.show || this.enableCancel
    },
    formatFormData() {
      let langType = localStorage.getItem('lang') || '中文'
      let val = {}
      getVal(this.instanceData.formData || {}, this.instanceData.formItems || [], val)
      val.ownerDept = this.instanceData.starterDept
      val.instanceId = this.instanceData.instanceId
      val.businessKey = this.instanceData.businessKey
      val.owner = this.instanceData.staterUser.name
      val.startTime = this.instanceData.startTime
      val.finishTime = this.instanceData.finishTime
      val.code = this.instanceData.instanceId
      val.langType = langType
      return val
    },
    status() {
      let status = {
        text: this.instanceData.status
      }
      switch (this.instanceData.result) {
        case 'RUNNING':
        case 'COMPLETE':
          status.type = ''
          status.img = null
          break
        case 'PASS':
          status.type = 'success'
          status.img = this.$getLocalRes('agree.png')
          break
        case 'CANCEL':
          status.type = 'info'
          status.img = this.$getLocalRes('recall.png')
          break
        case 'REFUSE':
          status.type = 'danger'
          status.img = this.$getLocalRes('refuse.png')
          break
      }
      return status
    },
    activeTasks() {
      let tasks = [];
      (this.instanceData.progress || []).forEach((task) => {
        if (task.isFuture) return;
        if (task.users) {
          task.users.forEach((tk) => {
            // console.log(tk.user && tk.user.id === this.loginUser.id && !this.$isNotEmpty(tk.finishTime)||this.$store.state.roles!='')
            if (tk.user && (tk.user.id === this.loginUser.id || this.$store.state.roles != '') && !this.$isNotEmpty(tk.finishTime)) {

              tasks.push(tk)
            }
          })
        } else {
          // console.log(this.$store.state.roles)
          if (task.user && (task.user.id === this.loginUser.id || this.$store.state.roles != '') && !this.$isNotEmpty(task.finishTime)) {
            tasks.push(task)
          }
        }
      })
      return tasks
    },
    formData() {
      //过滤出可编辑的表单字段
      let formFields = []
      let formData = {}
      this.getEnableEditForm(this.instanceData.formItems || [], formFields)
      formFields.forEach((k) => {
        formData[k] = this.instanceData.formData[k]
      })
      return formData
    },
    actionDesc() {
      switch (this.actionType) {
        case 'agree':
          return { tip: this.isRootUser ? this.$t('webAuto.notes') : this.$t('webAuto.ApprovalOpinion'), title: this.isRootUser ? this.$t('webAuto.submitApprove') : this.$t('webAuto.AgreeApprove') };
        case 'refuse':
          return { tip: this.$t('webAuto.FinalRejection'), title: this.$t('webAuto.RejectApproval') }
        case 'complete':
          return { tip: this.$t('webAuto.HandlingOpinions'), title: this.$t('webAuto.HandlingTasks') }
        case 'comment':
          return { tip: this.$t('webAuto.CommentContent'), title: this.$t('webAuto.AddComment') }
        case 'beforeAdd':
          return { tip: this.$t('webAuto.AddSignatureComments'), title: this.$t('webAuto.ApproversAhead') }
        case 'afterAdd':
          return { tip: this.$t('webAuto.AddSignatureComments'), title: this.$t('webAuto.ApproverRear') }
        case 'transfer':
          return { tip: this.$t('webAuto.TransferOpinions'), title: this.$t('webAuto.TransferApproval') }
        case 'execute':
          return { tip: this.$t('webAuto.CCComments'), title: this.$t('webAuto.OthersView') }
        case 'cancel':
          return { tip: this.$t('webAuto.ReasonRrevocation'), title: this.$t('webAuto.RevokeProcess') }
        case 'recall':
          return { tip: this.$t('webAuto.ReturnOpinion'), title: this.$t('webAuto.ReturnNode') }
      }
    },
  },
  data() {
    return {
      printVisible: false,
      actionVisible: false,
      printCheck: false,
      loading: false,
      actionLoading: false,
      actionType: 'agree',
      instanceData: {},
      agreeVisible: false,
      printTemplateConfig: {
        customPrint: false,
        printTemplate: '',
      },
      activeName: 'first',
      openItemCopy: false,
      copyPicker: false,
      rowLi: {},
      orgPicker: {
        multiple: false,
        selected: [],
        title: '选择人员',
        value: []
      },
    }
  },
  mounted() {
    this.getInstanceData()
    this.getPrintConfig()
  },
  methods: {
    // 抄送
    copyClick(row) {
      this.rowLi = row
      this.openItemCopy = true
      this.orgPicker.value = []
    },
    // 选择的人员的打开弹框
    selectUser() {
      this.orgPicker.title = this.$t('webAuto.CCRecipients')
      this.orgPicker.multiple = true
      this.copyPicker = true
      this.$refs.orgPicker.show()
    },
    // 选择的人员的确定
    selected(users) {
      this.orgPicker.value.length = 0
      this.orgPicker.value.push(...users)
    },
    // 弹框确定
    openItemCopyClick() {
      if (this.orgPicker.value.length > 0) {
        let ccArr = []
        this.orgPicker.value.forEach(itme => {
          ccArr.push(itme.id)
        })
        console.log(this.$store.state.loginUser.name)
        taskApi.processCopy({
          userId: this.$store.state.loginUser.id,
          instanceId: this.rowLi.instanceId,
          nodeId: this.$store.state.loginUser.id,
          nodeName: this.$store.state.loginUser.name,
          ccUsers: ccArr,
        }).then(rsp => {
          this.$message.success(this.$t('webAuto.CCSuccessful'))
          this.openItemCopy = false
        })
      } else {
        this.$message.warning(this.$t('webAuto.CCPersonnel'))
      }
    },
    //根据退回进行分段拆解
    splitByRecall(progress) {
      // //提取分段时间点
      // let points = progress
      //   .filter((p) => p.result === 'recall')
      //   .map((p) => new Date(p.startTime).getTime())
      // if (points.length > 0) {
      //   let blocks = [] //分段流程块组
      //   let pointer = 0 //定点索引
      //   points.push(new Date().getTime() + (1000 * 3600 * 24))
      //   points.forEach((point) => {
      //     let block = []
      //     for (let i = pointer; i < progress.length; i++) {
      //       let startTime = new Date(progress[i].startTime).getTime()
      //       if (startTime <= point) {
      //         block.push(progress[i])
      //       } else {
      //         pointer = i
      //         break
      //       }
      //     }
      //     //存段
      //     blocks.push(block)
      //   })
      //   //按段处理
      //   let processNodes = []
      //   blocks.forEach((block) => processNodes.push(...this.mergeTask(block)))
      //   return processNodes
      // }
      return this.mergeTask(progress)
    },
    isMergeNode(n, pg) {
      //节点合并条件，满足以下条件就合并节点，目前规则是如果节点ID相同，且时间相差在2S内，则认为该俩节点
      return n.nodeId === pg.nodeId && Math.abs(moment(n.startTime).diff(moment(pg.startTime))) <= 2000
    },
    //合并活动节点，此处执行一段合并算法用来处理退回导致节点重合的问题
    mergeTask(progress) {
      let merge = []
      progress.forEach((pg) => {
        let i = merge.findIndex((n) => this.isMergeNode(n, pg))
        if (i > -1) {
          //存在则合并到对象
          if (merge[i].users) {
            //已经合并过了
            merge[i].finishTime = pg.finishTime
            merge[i].users.push(pg)
            merge[i].result = this.getApprovalResult(
              merge[i],
              pg,
              pg.approvalMode
            )
            merge[i].comment = merge[i].comment.concat(pg.comment)
          } else {
            //没有就合并
            merge[i] = {
              agree: null,
              name: pg.name,
              isFuture: pg.isFuture,
              nodeType: pg.nodeType,
              approvalMode: pg.approvalMode,
              nodeId: pg.nodeId,
              result: this.getApprovalResult(merge[i], pg, pg.approvalMode),
              startTime: merge[i].startTime,
              finishTime: pg.finishTime,
              comment: merge[i].comment.concat(pg.comment),
              users: [merge[i], pg],
            }
            merge[i].comment = merge[i].comment.sort(
              (a, b) => moment(a.createTime) - moment(b.createTime)
            )
          }
        } else {
          merge.push(pg)
        }
      })
      return merge
    },
    getInstanceData() {
      this.loading = true
      getFormAndProcessProgress(this.instanceId, this.nodeId)
        .then((rsp) => {
          this.loading = false
          this.instanceData = rsp.data
          this.instanceData.progress = this.splitByRecall(rsp.data.progress)
        })
        .catch((err) => {
          this.loading = false
          this.$err(err, this.$t('webAuto.instanceDataFailed'))
        })
    },
    getApprovalResult(oldVal, newVal, mode) {
      if (mode === 'OR') {
        return newVal.result ? newVal.result : oldVal.result
      } else if (mode === 'AND') {
        let rs = oldVal.result || newVal.result
        return rs === 'recall' ? 'recall' : rs
      } else {
        return newVal.result ? newVal.result : oldVal.result
      }
    },
    comment() {
      this.actionType = 'comment'
      this.actionVisible = true
    },
    handler(action) {
      this.actionType = action
      this.actionVisible = true
    },
    doAction() {
      //只有审批同意或者提交才做表单校验
      if (this.actionType === 'agree' || this.actionType === 'complete') {
        this.$refs.form.validate((valid) => {
          if (valid) {
            this.$refs.action.submitAction()
          } else {
            this.actionVisible = false
            if (this.isMobile) {
              showFailToast(this.$t('webAuto.completeForm'))
            } else {
              this.$message.warning(this.$t('webAuto.completeForm'))
            }
          }
        })
      } else {
        this.$refs.action.submitAction()
      }
    },
    print() {
      this.printVisible = true
    },
    doPrint() {
      Print(this.printCheck ? this.$refs.print : this.$refs.print.$el)
    },
    scanQr() {
      this.$message.warning(this.$t('webAuto.ComingSoon'))
    },
    handlerOk() {
      console.log('处理---handlerOk')
      this.actionVisible = false
      this.$emit('handler-after')
    },
    getEnableEditForm(forms, fields) {
      forms.forEach((f) => {
        if (f.name === 'SpanLayout') {
          this.getEnableEditForm(f.props.items, fields)
        } else if (f.name === 'TableList') {
          fields.push(f.id)
        } else if (f.perm === 'E') {
          fields.push(f.id)
        }
      })
    },
    getPrintConfig() {
      getCustomPrintConfig(this.instanceId)
        .then((rsp) => {
          this.printTemplateConfig = rsp.data
        })
        .catch((err) => {
          this.$err(err, this.$t('webAuto.templateConfiguration'))
        })
    },
    renderPrint(val) {
      if (val) {
        this.$nextTick(() => {
          bindVar(
            this.printTemplateConfig.printTemplate,
            this.formatFormData,
            'printDom'
          )
        })
      }
    },
    updeatePage() {
      // console.log('修改表单')
      // this.formData.storeForm='storeForm'
      let params = {
        instanceId: this.instanceId,
        formData: this.formData,
      }
      updateInstanceFormData(params).then(rsp => {
        this.$emit('handler-after')
        this.$ok(rsp, this.$t('webAuto.FormUpdatedSuccessfully'))
        this.actionVisible = false
      }).catch(err => {
        // this.$emit('fail')
        this.$err(err, this.$t('webAuto.FormUpdateFailed'))
      })
    }
  },
  emits: ['handler-after'],
}
</script>

<style lang="less" scoped>
.preview {
  background: #fff;
  position: relative;
  height: 100%;
  overflow: hidden;

  &>div:nth-child(1) {
    overflow-y: auto;
    overflow-x: hidden;
    height: 100%;
    //padding-bottom: 50px;
  }

  .actions {
    height: 30px;
    padding: 15px 0;
    position: fixed;
    width: 100%;
    bottom: 0;
    left: 0;
    z-index: 99;
    background: white;
    border-top: 1px solid #dcdfe6;
    box-shadow: 0 0 15px 0px #dad8d8;

    .ok-refuse {
      position: absolute;
      right: 20px;
    }

    .action-more {
      position: absolute;
      right: 180px;
      top: 5px;
    }

    .cancel {
      position: absolute;
      background: white;
      right: 20px;
      top: 5px;
    }

    .cancel2 {
      position: absolute;
      background: white;
      right: 87px;
      top: 0;
    }

    .cancel3 {
      position: fixed;
      background: white;
      right: 10px;
      bottom: 0;
    }

    .comment {
      position: absolute;
      left: 20px;
      top: -5px;
      cursor: pointer;
      text-align: center;
      font-size: 12px;

      :deep(.icon) {
        font-size: 20px;
      }

      &:hover {
        color: @theme-primary;
      }
    }
  }
}

.process {
  background: white;
  // padding: 20px 10px 50px 10px;
}

.title-div {
  // position: fixed;
  z-index: 9999;
  top: 50px;
  right: 0;
  width: 100%;

}

.title {
  background: white;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  position: relative;
  padding: 0 10px 10px 10px;

  &>div {
    color: #666666;
    display: inline-block;
  }

  .title-info {
    height: 50px;
    display: flex;
    padding: 0 10px;
    position: relative;
    flex-direction: column;
    justify-content: space-between;

    .name {
      font-size: 15px;
      color: #5e5e5e;
    }

    .code {
      font-size: 13px;
    }

    img {
      width: 80px;
      height: 80px;
      position: absolute;
      right: -100px;
      top: 30px;
      z-index: 9999;
    }
  }

  .extend-options {
    position: absolute;
    right: 0;

    :deep(.icon) {
      cursor: pointer;
      margin-right: 20px;

      &:hover {
        color: @theme-primary;
      }
    }
  }
}

.form {
  margin: 15px 0;
  padding: 10px 10px 1px 10px;
  background: white;
}

.container-box {
  // margin: 70px 0 55px 0;
  background: white;
}

.container-box2 {
  // margin: 80px 0 0 0;
  background: white;
}

.root {
  margin-bottom: 50px;
}

.actions2 {
  bottom: -50px !important;
}
</style>
